﻿/********************************************************************************
* Copyright 2010 Zane Thorn (zane.thorn@gmail.com)                              *
*                                                                               *
* NeturalMath is free software: you can redistribute it and/or modify           *
* it under the terms of the GNU Lesser General Public License as published by   *
* the Free Software Foundation, either version 3 of the License, or             *
* (at your option) any later version.                                           *
*                                                                               *
* NeturalMath is distributed in the hope that it will be useful,                *
* but WITHOUT ANY WARRANTY; without even the implied warranty of                *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the                 *
* GNU Lesser General Public License for more details.                           *
*                                                                               *
* You should have received a copy of the GNU Lesser General Public License      *
* along with NeturalMath.  If not, see <http://www.gnu.org/licenses/>.          *
********************************************************************************/

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace NeturalMath.Expressions
{
	public class DefVisitor:MathExpressionVisitor<string>
	{
	    public DefVisitor(MathRuntime runtime) : base(runtime)
	    {
	    }

	    protected override string VisitAssignment(AssignmentExpression expression)
        {
            var id = Visit(expression.Target);
            var exp = Visit(expression.Assignment);
            return string.Format("{0} = {1}", id, exp);
        }


        protected override string VisitBinaryOperator(BinaryOperatorExpression expression)
        {
            var left = Visit(expression.Left);
            var right = Visit(expression.Right);
            string op = string.Empty;

            switch (expression.OperatorType)
            {
                case BinaryOperatorType.Add:
                    op = "+";
                    break;
                case BinaryOperatorType.Subtract:
                    op = "-";
                    break;
                case BinaryOperatorType.Multiply:
                    op = "*";
                    break;
                case BinaryOperatorType.Divide:
                    op = "/";
                    break;
                case BinaryOperatorType.Modulo:
                    op = "%";
                    break;
                case BinaryOperatorType.Power:
                    op = "^";
                    break;
                case BinaryOperatorType.And:
                    op = "&";
                    break;
                case BinaryOperatorType.Or:
                    op = "|";
                    break;
                case BinaryOperatorType.Xor:
                    op = "><";
                    break;
                case BinaryOperatorType.Equal:
                    op = "==";
                    break;
                case BinaryOperatorType.NotEqual:
                    op = "<>";
                    break;
                case BinaryOperatorType.GreaterThan:
                    op = ">";
                    break;
                case BinaryOperatorType.GreaterThanOrEqual:
                    op = ">=";
                    break;
                case BinaryOperatorType.LessThan:
                    op = "<";
                    break;
                case BinaryOperatorType.LessThanOrEqual:
                    op = "<=";
                    break;
                case BinaryOperatorType.Range:
                    op = "->";
                    break;
                default:
                    throw new NotSupportedException();
            }

            return string.Format("({0} {1} {2})", left, op, right);
        }

        protected override string VisitDomain(DomainExpression expression)
        {
            var builder = new StringBuilder();
            builder.AppendLine("{");

            foreach (var e in expression.Expressions)
                builder.AppendLine(Visit(e));

            builder.AppendLine("}");

            return builder.ToString();
        }


	    protected override string VisitConstant(ConstantValueExpression expression)
	    {
	        return expression.Value.ToString();
	    }

	    protected override string VisitFunctionCall(FunctionUseExpression expression)
	    {
	        var builder = new StringBuilder(expression.MemberName);
            var isSet = false;

	        builder.Append("(");
            foreach (var p in expression.Parameters)
            {
                if (isSet)
                    builder.Append(", ");
                if (!isSet) isSet = true;

                builder.Append(Visit(p));
            }
	        builder.Append(")");

	        return builder.ToString();
	    }

	    protected override string VisitImportKeyword(ImportKeywordExpression expression)
	    {
            return "import " + expression.ImportPath;
	    }

	    protected override string VisitMemberLookup(LookupExpression expression)
	    {
            return expression.MemberName;
	    }

	    protected override string VisitDefKeyword(DefKeywordExpression expression)
	    {
	        var builder = new StringBuilder("def ");
            foreach (var p in expression.Expressions)
            {
                builder.Append(Visit(p));
                builder.Append(", ");
            }
            
	        return builder.ToString();
	    }

	    protected override string VisitPrintKeyword(PrintKeywordExpression expression)
	    {
            var builder = new StringBuilder("print ");
            foreach (var p in expression.Expressions)
            {
                builder.Append(Visit(p));
                builder.Append(", ");
            }

            return builder.ToString();
	    }



        protected override string VisitParameterExpression(FunctionParameterExpression expression)
        {
            throw new NotImplementedException();
        }

        protected override string VisitUnaryOperator(UnaryOperatorExpression expression)
        {
            throw new NotImplementedException();
        }

        protected override string VisitDelegate(DelegateExpression expression)
        {
            throw new NotImplementedException();
        }

        protected override string VisitSymbolicLookup(SymbolicLookupExpression expression)
        {
            throw new NotImplementedException();
        }
    }
}
